/*
 *  game_ui.cpp
 *  BioBreak
 *
 *  Created by terry franguiadakis on 2/22/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */
// -----------------------------------------------------------------------------

#include "ui_elements.h"
#include "texture.h"
#include "mathutils.h"
#include "player.h"
#include "timermgr.h"

/*--------------------------------------------------------------------------*/
//Global Implementation
const CTexture*	GetButtonTexture(EClass i_objClass, bool i_selected)
{
	const CTexture* foundTexture = NULL;
	switch (i_objClass)
	{
		case EClass_Nucleus:
			{
				if (!i_selected)
				{
					foundTexture = g_texturemgr.CreateTexture("button_nucleus.png");
				}
				else
				{
					foundTexture = g_texturemgr.CreateTexture("button_nucleus_used.png");
				}
			}
			break;
		case EClass_ExpansionNode:
			{
				if (!i_selected)
				{
					foundTexture = g_texturemgr.CreateTexture("button_expansionnode.png");
				}
				else
				{
					foundTexture = g_texturemgr.CreateTexture("button_expansionnode_used.png");
				}
			}
			break;
		case EClass_HealStation:
			{
				if (!i_selected)
				{
					foundTexture = g_texturemgr.CreateTexture("button_healStation.png");
				}
				else
				{
					foundTexture = g_texturemgr.CreateTexture("button_healStation_used.png");
				}
			}
			break;
		case EClass_BasicWeapon:
			{
				if (!i_selected)
				{
					foundTexture = g_texturemgr.CreateTexture("button_weapon_basic.png");
				}
				else
				{
					foundTexture = g_texturemgr.CreateTexture("button_weapon_basic_used.png");
				}
			}
			break;
		case EClass_MiningStation:
			{
				if (!i_selected)
				{
					foundTexture = g_texturemgr.CreateTexture("button_miningStation.png");
				}
				else
				{
					foundTexture = g_texturemgr.CreateTexture("button_miningStation_used.png");
				}
			}
			break;
		
		default:
			{
				foundTexture = g_texturemgr.GetMissingTexture();
			}
			break;
	}
	
	return foundTexture;
}

/*--------------------------------------------------------------------------*/
//BBUIElement Implementation
BBUIElement::BBUIElement()
{
	m_textureUI = NULL;
	m_isVisible = true;
}
	

/*--------------------------------------------------------------------------*/
//BBBackElement Implementation	
bool BBBackElement::IsPointContained(const Vector2f& i_pos)
{
        Vector2f mmin(0,440), mmax(320, 480);
        if (mmin < i_pos && i_pos < mmax)
            return true;
        else 
            return false;
}

void BBBackElement::Render()
{
	Vector2f mmin(0,440), mmax(320, 480);
 
	g_texturemgr.EnableTextures(true);
	GetTextureUI()->Apply();
		
	m_transform.PushMatrix();
	BasicDrawObjects::DrawTexturedRect(mmin, mmax, Color4f(), Vector2f(0.0f, 0.0f), Vector2f(1.0f, 1.00f));
	m_transform.PopMatrix();
	
	g_texturemgr.EnableTextures(false);
}

/*--------------------------------------------------------------------------*/
CTextureCounter* BBUIButton::s_price = NULL;



//BBUIButton Implementation
BBUIButton::BBUIButton(const Vector2f& i_pos, float i_size, EClass i_spawnClass, EButtonFunction i_buttonContext)
{
	m_buttonContext = i_buttonContext;
	m_spawnClass = i_spawnClass;
	m_transform.SetPos(i_pos);
	m_transform.SetScale(i_size);
	m_state = EState_Usable;
	
	SetTextureUI(GetButtonTexture(i_spawnClass, false));
	m_textureUIUsed = GetButtonTexture(i_spawnClass, true);
    
    if (!s_price)
    {
        s_price = g_texturemgr.CreateTextureCounter();
    }
}
    
bool BBUIButton::IsPointContained(const Vector2f& i_pos)
{
	if (Dist(i_pos, m_transform.GetPos()) <= m_transform.GetScale())
	{
		return true;
	}
	return false;
}

void BBUIButton::Apply(const Vector2f& i_pos)
{	
	if (m_state != EState_Usable)
	{
		return;
	}
	
	switch(m_buttonContext)
	{
	case EButtonFunction_GoCreator:
		{
			//don't apply if we don't have enough money for some reason!
			int cost = g_gomgr.GetClassCost(m_spawnClass);
			if (g_player.GetMineralCount() >= cost)
			{
				Vector2f wp = convertPosToWorldSpace(i_pos);
				g_gomgr.On_UICreateGoPlacingNode(m_spawnClass, wp);
				g_player.AddMinerals(-g_gomgr.GetClassCost(m_spawnClass));
				setState(EState_InUse);
			}
		}
		break;
	}
}
    
void BBUIButton::Remove()
{
	if (m_state == EState_InUse)
	{
		g_gomgr.On_UIDestoryCurrentGoPlacingNode();
		
		//give back the money
		g_player.AddMinerals(g_gomgr.GetClassCost(m_spawnClass));
		
		setState(EState_Usable);
	}
}

bool BBUIButton::IsPlaced()
{
	if (m_state == EState_InUse)
	{
		return g_gomgr.On_IsGoPlacingNodePlaced();
	}
	
	return false;
}

void BBUIButton::ClearPlaced()
{
	if(EState_InUse == m_state)
	{
		setState(EState_Usable);
	}
}

void BBUIButton::setState(EState i_state)
{
	m_state = i_state;
}

void BBUIButton::Update()
{
	if (m_buttonContext == EButtonFunction_GoCreator)
	{
		int cost = g_gomgr.GetClassCost(m_spawnClass);
		
		switch(m_state)
		{
		case EState_Usable:
			{
				//if we don't have enough minerals... then disable it
				if (g_player.GetMineralCount() < cost)
				{
					setState(EState_Disabled);
				}
			}
			break;
		case EState_Disabled:
			{
				//if we have enough.. then enable it
				if (g_player.GetMineralCount() >= cost)
				{
					setState(EState_Usable);
				}
			}
			break;
		}
	}
}

void BBUIButton::Render()
{	
	Vector2f mmin(-.5,-.4), mmax(.5,.4);
	Color4f	color;
	g_texturemgr.EnableTextures(true);
	
	switch(m_state)
	{
	case EState_InUse:
		{
			m_textureUIUsed->Apply();
		}
		break;
	case EState_Disabled:
		{
			//make the button look un-usable
			color.b = 0.5;
			color.g = 0.5f;
			color.a = 0.3f;
		}
		//fall through to use in use texture!
	case EState_Usable:
		{
			GetTextureUI()->Apply();
		}
		break;
	}

	m_transform.PushMatrix();
	BasicDrawObjects::DrawTexturedRect(mmin, mmax, color, Vector2f(0.0f, 0.0f), Vector2f(1.0f, 1.00f));
    
	m_transform.PopMatrix();
	
    Transform2D fontxform = m_transform;
    fontxform.SetScale(1.5f);
    Vector2f pos = fontxform.GetPos();
    pos.x -= 22.0f;
    fontxform.SetPos(pos);
    fontxform.PushMatrix();
    renderPrice();
    fontxform.PopMatrix();
    
	g_texturemgr.EnableTextures(false);
}

void BBUIButton::renderPrice()
{
    if (s_price && m_spawnClass != EClass_Invaild)
    {
        char pricestr[25];
        sprintf(pricestr, "%d", g_gomgr.GetClassCost(m_spawnClass));
        s_price->SetString(pricestr);
        s_price->SetInterval(10,20);
        s_price->Draw(Vector2f::Zero, Color4f(0,0,0,1));
    }
}

Vector2f BBUIButton::convertPosToWorldSpace(const Vector2f& i_pos)
{
	// - transform into view
	Vector2f wp = g_camera.ScreenToCameraSpace(i_pos);
	return wp + g_camera.GetPos();
}

/*--------------------------------------------------------------------------*/
CTextureCounter* CUITimer::s_timerCounter = NULL;

CUITimer::CUITimer(const Vector2f& i_pos)
{
	m_state = EState_InActive;
	m_timeLeft = 0.0f;
	m_isVisible = false;
	
	if (!s_timerCounter)
	{
		s_timerCounter = g_texturemgr.CreateTextureCounter();
	}
	
	m_transform.SetPos(i_pos);
}

void CUITimer::Render()
{
	if (!m_isVisible || (m_state == EState_InActive))
	{
		return;
	}
	
	g_texturemgr.EnableTextures(true);
	
	Transform2D fontxform = m_transform;
    fontxform.SetScale(3.0f);
	
    fontxform.PushMatrix();
    
	//render out the number of seconds left
	char timerBuffer[25];
	//add one to the count so you never see 0 
	//(also makes it feel like X seconds when you get to see the number X)
	sprintf(timerBuffer, "%d", (int)m_timeLeft + 1);
	s_timerCounter->SetString(timerBuffer);
	s_timerCounter->SetInterval(10,20);
	s_timerCounter->Draw(Vector2f::Zero, Color4f(0.0f, 0.0f, 0.0f, 1.0f));
	
    fontxform.PopMatrix();
    
	g_texturemgr.EnableTextures(false);
}

void CUITimer::setState(EState i_state)
{	
	m_state = i_state;
	
	switch(m_state)
	{
	case EState_InActive:
		{
			m_isVisible = false;
		}
		break;
	}
}

void CUITimer::Update()
{
	switch(m_state)
	{
	case EState_Running:
		{
			//remove the amount of time
			m_timeLeft -= Dt();
			m_timeLeft = BBMAX(m_timeLeft, 0.0f);
			
			//is there time left?
			if (m_timeLeft == 0.0f)
			{
				setState(EState_Complete);
			}
		}
		break;
	case EState_Complete :
		{
			//$$ (SAW) we might want to let this sit around so systems can ask if completed
			// or show zero for a second.. but for now.. just go to inactive
			setState(EState_InActive);
		}
		break;
	}
}

void CUITimer::SetTimer(float i_timeLeft)
{
	m_timeLeft = i_timeLeft;
}

void CUITimer::StartTimer()
{
#if DEBUG
	if (IsNearZero(m_timeLeft))
	{
		printf("Error: Time needs to be set before starting the timer. If not timer will completed");
		return;
	}
#endif // DEBGUG

	m_isVisible = true;
	setState(EState_Running);
}

void CUITimer::PauseTimer()
{
#if DEBUG
	if (m_state != EState_Running)
	{
		printf("Error: Timer is not running");
		return;
	}
#endif // DEBGUG
	
	setState(EState_Paused);
}

void CUITimer::StopTimer()
{
#if DEBUG
	if (m_state != EState_Running)
	{
		printf("Error: Timer is not running");
		return;
	}
#endif // DEBGUG

	setState(EState_InActive);
}

/*--------------------------------------------------------------------------*/
//CProgressBar Implementation
// -----------------------------------------------------------------------------
CProgressBar::CProgressBar()
{
	m_width = 1.0f;
	m_height = 0.3f;
	m_bgColor = Color4f(1.0f, 0.0f, 0.0f, 1.0f);
	m_progressColor = Color4f(0.0f, 1.0f, 0.0f, 1.0f);
	m_progress = 1.0f;
	m_isVisible = false;
}

void CProgressBar::Render()
{
	if (!m_isVisible)
	{
		return;
	}
	
	float heightRatio =  m_height / m_width;
	Vector2f bgmin(-0.5f, -0.5f * heightRatio);
	Vector2f bgmax(0.5f, 0.5f * heightRatio);
	
	Vector2f progressMin(-0.5f, -0.5f * heightRatio);
	Vector2f progressMax(-0.5f + m_progress, 0.5f * heightRatio);
	
    m_transform.PushMatrix();
	BasicDrawObjects::DrawSolidRect(bgmin, bgmax, m_bgColor);
	BasicDrawObjects::DrawSolidRect(progressMin, progressMax, m_progressColor);
    m_transform.PopMatrix();
}

void CProgressBar::SetProgress(float i_progress)
{
	//ensure the value is between 0.0 and 1.0
	i_progress = BBMIN(BBMAX(i_progress, 0.0f), 1.0f);
	m_progress = i_progress;
}

void CProgressBar::SetWidth(float i_width)
{
	//ensure the value is between 0.0 and 1.0
	i_width = BBMIN(BBMAX(i_width, 0.0f), 1.0f);
	m_width = i_width;
}

void CProgressBar::SetHeight(float i_height)
{
	//ensure the value is between 0.0 and 1.0
	i_height = BBMIN(BBMAX(i_height, 0.0f), 1.0f);
	m_height = i_height;
}

/*-----------------------------------EOF!-----------------------------------*/
